# coding=utf-8
import datetime
import os
import sys
import struct
import time
import json
import logging
import urllib
import urllib2
from urllib import urlencode

reload(sys)
sys.setdefaultencoding('utf-8')

logger = logging.getLogger()
logger.setLevel(logging.INFO)
sh = logging.StreamHandler(stream=sys.stdout)  # output to standard output
sh.setFormatter(logging.Formatter("%(asctime)s - %(message)s"))
logger.addHandler(sh)

cache_details = {}
auths = []
auth_index = 0

last_sync_time = 0
scan_items = []
item_interval = 1.0

##server_root = "http://127.0.0.1:8080/douya/purchaser/"
server_host = "139.9.55.19"
server_root = "http://" + server_host + ":8080/douya/purchaser/"
scan_count = 0
find_count = 0
version = "v1.2"


def get_ext_ip():
    try:
        url = "http://" + server_host + ":8080/douya/ip/getIpInfo.do"
        req = urllib2.Request(url)
        response = urllib2.urlopen(req)
        res = response.read()
        res = json.loads(res)
        if res["ret"] == 0:
            return res["ip"]
    except Exception, e:
        logger.error(e)
        return ""


def item_detail(item, name):
    classid = item["classid"]
    instanceid = item["instanceid"]
    appid = item["appid"]

    try:
       ## https://www.c5game.com/steam/item/detail.html?classid=1723106292&instanceid=1723145900&appid=570
        url_base = "https://www.c5game.com/steam/item/detail.html?classid={0}&instanceid={1}&appid={2}&locale=zh"
        url = url_base.format(classid, instanceid, appid)
        logger.info("request url= " + url)
        req = urllib2.Request(url)
        response = urllib2.urlopen(req)
        res = response.read()
        name = name.encode('utf-8')
        if res.index(name) > -1:
            return res

    except Exception, e:
        logger.error(e)
    return ""


def fill_detail(items, name):
    global cache_details
    if len(cache_details) > 0:
        cache_details = {}
    for item in items:
        id = item["id"]
        if id in cache_details:
            item["detail"] = cache_details[id]
        else:
            detail = item_detail(item, name)
            if detail == "":
                logger.error("can not get detail from item id: {0}, name: {1}".format(id, name))
                continue
            cache_details[id] = detail
            item["detail"] = detail


def sell_order(scan_item):
    try:
        url_base = "https://www.c5game.com/api/product/sale.json?id={0}&quick=&gem_id=0&page=1&flag=&delivery" \
                   "=&sort=&b1=&style=&locale=zh"
        url = url_base.format(scan_item["tagId"])
        logger.info("request url= " + url)
        req = urllib2.Request(url)
        response = urllib2.urlopen(req)
        res = response.read()
        res = json.loads(res)
        if res["status"] == 200:
            logger.info("ok, item size: " + str(len(res["body"]["items"])))
            items = res["body"]["items"]
            fill_detail(items, scan_item["name"])
            return items
        else:
            logger.info(res)
    except Exception, e:
        logger.error(e)


def sync_auth():
    try:
        global auths
        global server_root

        auth_url = server_root + "getC5Auth.do"
        logger.info("sync auth {0}".format(auth_url))
        headers = {'Content-Type': 'application/json', 'Accept': 'application/json, text/javascript, */*; q=0.01'}
        req = urllib2.Request(auth_url, headers=headers)
        response = urllib2.urlopen(req)
        res = response.read()
        logger.info(res)
        response = json.loads(res)
        if response["code"] == 0:
            auths = response["auths"]
        else:
            logger.info("sync autf error:")
            auths = []
    except Exception, e:
        auths = []
        logger.info("sync autf error:")
        logger.error(e)


def sync_task():
    global last_sync_time
    global scan_items
    global server_id
    global scan_count
    global find_count
    global item_interval
    global server_root

    sync_url = server_root + "syncTask.do"
    logger.info("sync task {0}".format(sync_url))
    try:
        data = {
            "serverId": server_id,
            "scanCount": scan_count,
            "findCount": find_count,
            "workerVersion": version,
            "itemReporters": []
        }
        for item in scan_items:
            data["itemReporters"].append({
                "scanCount": item["scanCount"],
                "findCount": item["findCount"],
                "itemId": item["id"],
            })

        logger.info("request url= " + sync_url + " data = " + json.dumps(data))
        headers = {'Content-Type': 'application/json', 'Accept': 'application/json, text/javascript, */*; q=0.01'}
        req = urllib2.Request(sync_url, headers=headers, data=json.dumps(data))
        response = urllib2.urlopen(req)
        res = response.read()
        logger.info(res)
        response = json.loads(res)
        if response["code"] == 0:
            items = response["data"]
            worker = response["worker"]
            for item in items:
                item["scanCount"] = 0
                item["findCount"] = 0
            scan_items = items
            if worker:
                item_interval = worker["itemInterval"]
        scan_count = 0
        find_count = 0
    except Exception, e:
        logger.error(e)


def sync_if_need():
    global last_sync_time
    now = datetime.datetime.now()
    if last_sync_time != 0 and (now - last_sync_time).total_seconds() < 15:
        return
    last_sync_time = now
    sync_task()
    sync_auth()


def buy(item, scan_item):
    try:
        global auths
        global auth_index
        if(len(auths) == 0):
            logger.error("no authentication")
            post_buy_result(item, scan_item, "没有认证", -1)
            return
        auth_index += 1
        if auth_index == len(auths):
            auth_index = 0
        auth = auths[auth_index]

        ## https://www.c5game.com/api/order/payment.json
        url = "https://www.c5game.com/api/order/payment.json"
        post = "id={0}&price={1}&method=4&coupon=&coupon_amount=&buy_secret=".format(item["id"], item["price"])
        if "paypwd" in auth and auth["paypwd"] != "":
            post += "&paypwd={0}&is_nopass=off".format(auth["paypwd"])
        cookie = auth["cookie"]
        headers = {
            "origin": "https://www.c5game.com",
            "x-requested-with": "XMLHttpRequest",
            "Content-Type": "application/x-www-form-urlencoded",
            "referer": "https://www.c5game.com/dota/14896839-S.html?buy_secret=",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
                          "Chrome/75.0.3770.100 Safari/537.36",
            "cookie": cookie
        }
        logger.info("buy request url= " + url + " post=" + post)
        req = urllib2.Request(url, data=post, headers=headers)
        response = urllib2.urlopen(req)
        res = response.read()
        res = json.loads(res.decode('unicode_escape'))
        logger.info(res)
        if res["status"] == 200:
            logger.info("buy success")
            post_buy_result(item, scan_item, "购买成功", 1)
        else:
            logger.info(res["message"])
            post_buy_result(item, scan_item, res["message"], -1)
    except Exception, e:
        logger.error(e)
        post_buy_result(item, scan_item, "认证失效", -1)


def need_buy(sell_item, scan_item):
    threshold_price = float(scan_item["price"])
    sell_price = float(sell_item["price"])

    if sell_price > threshold_price:
        return False
    detail = sell_item["detail"]
    properties = scan_item["property"].encode('utf-8')
    properties = properties.split('$')
    match_count = 0
    for pro in properties:
        if not pro.startswith('!') and detail.find(pro) > -1:
            return True
        elif pro.startswith('!') and detail.find(pro[1:]) == -1:
            match_count += 1

    if match_count == len(properties):
        return True
    return False


def post_buy_result(item, scan_item, msg, ret):
    try:
        global server_root
        global server_id
        url = server_root
        url += "buy.do?itemId={0}&clientId={1}&goodsId={2}&msg={3}&ret={4}&serverId={5}" \
            .format(scan_item["id"], "", item["id"], urllib.quote(msg.encode('utf-8')), ret, server_id)
        logger.info("post buy result url: " + url)
        req = urllib2.Request(url)
        response = urllib2.urlopen(req)
        res = response.read()
        logger.info(res)
        response = json.loads(res)
        if response["code"] == 0:
            logger.info("post buy result ")
        else:
            logger.info("post buy result ")
    except Exception, e:
        logger.error(e)


def notify(item):
    try:
        global server_root
        global server_id
        url = server_root
        url += "record.do?goodsId={0}&userId={1}&serverId={2}&scanId={3}&scanName={4}&price={5}&platform=c5game"\
            .format(item["id"], item["owner"]["id"], server_id, item["item_id"], urllib.quote(item["name"].encode('utf-8')), item["price"])
        req = urllib2.Request(url)
        response = urllib2.urlopen(req)
        res = response.read()
        logger.info(res)
        response = json.loads(res)
        if response["code"] == 0:
            logger.info("notify server success")
        else:
            logger.info("notify server error")
    except Exception, e:
        logger.error(e)


def run_one():
    global scan_items
    global scan_count
    global find_count
    sync_if_need()
    for scan_item in scan_items:
        try:
            sell_items = sell_order(scan_item)
            for sell_item in sell_items:
                if need_buy(sell_item, scan_item):
                    logger.info("need buy item: %s", scan_item["name"])
                    find_count = find_count + 1
                    buy(sell_item, scan_item)
                    notify(sell_item)
            scan_item["scanCount"] = scan_item["scanCount"] + 1
            scan_count = scan_count + 1
            time.sleep(item_interval)
        except Exception, e:
            logger.error(e)



server_id = get_ext_ip()
if server_id == "":
    logger.error("can't get ext ip")
    exit(-1)

server_id += ".c5"

logger.info("set service id: %s", server_id)

while True:
    try:
        run_one()
    except Exception, e:
        logger.error(e)
